package jbase.project.system.core;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

public class ExtClassloader extends ClassLoader {

	@Override
	public URL getResource(String name) {
		return clazzSource.getResource(name);
	}

	@Override
	public Enumeration<URL> getResources(String name) throws IOException {
		return clazzSource.getResources(name);
	}

	@Override
	protected URL findResource(String name) {
		return clazzSource.findResource(name);
	}

	@Override
	protected Enumeration<URL> findResources(String name) throws IOException {
		return clazzSource.findResources(name);
	}

	@Override
	public InputStream getResourceAsStream(String name) {
		return clazzSource.getResourceAsStream(name);
	}

	@Override
	protected Package getPackage(String name) {
		return clazzSource.getPackage(name);
	}

	@Override
	protected Package[] getPackages() {
		return clazzSource.getPackages();
	}

	public static interface ClazzSource {
		public byte[] getClazzBytes(String className) throws Exception;

		public Enumeration<URL> findResources(String name) throws IOException;

		public URL getResource(String name);

		public Enumeration<URL> getResources(String name) throws IOException;

		public URL findResource(String name);

		public InputStream getResourceAsStream(String name);

		public Package getPackage(String name);

		public Package[] getPackages();
	}

	private Map<String, Class<?>> clazzPool = new HashMap<String, Class<?>>();

	private ClazzSource clazzSource;

	public ExtClassloader(ClassLoader parent, ClazzSource clazzSource, Map<String, Class<?>> pool) {
		super(parent);
		this.clazzSource = clazzSource;
		this.clazzPool.putAll(pool);
	}

	public Map<String, Class<?>> getClazzPool() {
		return this.clazzPool;
	}

	@Override
	public Class<?> findClass(String name) throws ClassNotFoundException {
		Class<?> clazz = null;
		if (clazzPool.containsKey(name)) {
			clazz = clazzPool.get(name);
		} else {
			byte[] clazzBytes;
			try {
				clazzBytes = clazzSource.getClazzBytes(name);
			} catch (Exception e) {
				throw new ClassNotFoundException("未能获取类：" + name + "的字节码！");
			}
			clazz = defineClass(name, clazzBytes, 0, clazzBytes.length);
			clazzPool.put(name, clazz);
		}
		return clazz;
	}

}
